#include "b_queen.h"

#include "board.h"
#include "gameengine.h"
#include <iostream>

using namespace std;

Queen::Queen() {
}

Queen::Queen(int r, int c , Color color) {
	row = r;
	col = c;
	pColor = color;
	setImage();
}


Queen::~Queen() {

}

void Queen::setImage() {
	if(pColor==white) {
		image = W_QUEEN;
	} else {
		image = B_QUEEN;
	}
}


void Queen::GetAllPossible(std::vector <Cell>  & moves) {
	bool oneStop = false;
	bool twoStop = false;
	bool threeStop = false;
	for( int i = 1 ; i <= 7 ; i++) {
		if(MyFunctions::isInRange(row+i,col+i) && !oneStop) {
			moves.push_back(Cell(row+i,col+i));
			if(myBoard->hasEnemy(pColor,row+i,col+i)) {
				oneStop = true;
			}
			if(myBoard->hasTeamate(pColor,row+i,col+i)) {
				moves.pop_back();
				oneStop = true;
			}
		}
		if(MyFunctions::isInRange(row+i,col-i) && !twoStop) {
			moves.push_back(Cell(row+i,col-i));
			if(myBoard->hasEnemy(pColor,row+i,col-i)) {
				twoStop = true;
			}
			if(myBoard->hasTeamate(pColor,row+i,col-i)) {
				moves.pop_back();
				twoStop = true;
			}
		}
                //
                iHateCheckstyle(row,col,threeStop,i,moves);
	}
	SearchMoreMoves(moves);

}

void Queen::iHateCheckstyle(int row , int col , bool & threeStop , int i ,
                            std::vector<Cell> & moves){
    if(MyFunctions::isInRange(row+i,col) && !threeStop) {
            moves.push_back(Cell(row+i,col));
            if(myBoard->hasEnemy(pColor,row+i,col)) {
                    threeStop = true;
            }
            if(myBoard->hasTeamate(pColor,row+i,col)) {
                    moves.pop_back();
                    threeStop = true;
            }
    }
}

void Queen::SearchMoreMoves(std::vector<Cell> & moves) {
	bool oneStop = false;
	bool twoStop = false;
	bool threeStop = false;
	for( int i = 1 ; i <= 7 ; i++) {
		if(MyFunctions::isInRange(row-i,col+i) && !oneStop) {
			moves.push_back(Cell(row-i,col+i));
			if(myBoard->hasEnemy(pColor,row-i,col+i)) {
				oneStop = true;
			}
			if(myBoard->hasTeamate(pColor,row-i,col+i)) {
				moves.pop_back();
				oneStop = true;
			}
		}
		if(MyFunctions::isInRange(row-i,col-i) && !twoStop) {
			moves.push_back(Cell(row-i,col-i));
			if(myBoard->hasEnemy(pColor,row-i,col-i)) {
				twoStop = true;
			}
			if(myBoard->hasTeamate(pColor,row-i,col-i)) {
				moves.pop_back();
				twoStop = true;
			}
		}

                //
                iHateCheckstyle2(row,col,threeStop,i,moves);

	}
	SearchEvenMoreMoves(moves);
}

void Queen::iHateCheckstyle2(int row , int col , bool & threeStop , int i ,
                            std::vector<Cell> & moves){
    if(MyFunctions::isInRange(row-i,col) && !threeStop) {
            moves.push_back(Cell(row-i,col));
            if(myBoard->hasEnemy(pColor,row-i,col)) {
                    threeStop = true;
            }
            if(myBoard->hasTeamate(pColor,row-i,col)) {
                    moves.pop_back();
                    threeStop = true;
            }
    }
}

void Queen::SearchEvenMoreMoves(std::vector<Cell> & moves) {
	bool leftStop = false;
	bool rightStop = false;
	for( int i = 1 ; i <= 7 ; i++) {
		if(MyFunctions::isInRange(row,col-i) && !leftStop) {
			moves.push_back(Cell(row,col-i));
			if(myBoard->hasEnemy(pColor,row,col-i)) {
				leftStop = true;
			}
			if(myBoard->hasTeamate(pColor,row,col-i)) {
				moves.pop_back();
				leftStop = true;
			}
		}

		if(MyFunctions::isInRange(row,col+i) && !rightStop) {
			moves.push_back(Cell(row,col+i));
			if(myBoard->hasEnemy(pColor,row,col+i)) {
				rightStop = true;
			}
			if(myBoard->hasTeamate(pColor,row,col+i)) {
				moves.pop_back();
				rightStop = true;
			}
		}
	}
}

bool Queen::isPiece() {
	return true;
}


void Queen::setCell(int r, int c) {
	row = r;
	col = c;
}

Color Queen::GetColor() {
	return pColor;
}

ImageName Queen::GetImage() {
	return image;
}


bool Queen::Test(std::ostream &os) {
	bool success = true;
	if (!Queen::TestMoves(std::cout)) success = false;
	if (!Queen::TestCheck(std::cout)) success = false;
	return success;
}

bool Queen::TestMoves(std::ostream &os) {

	bool success = true;

	GameEngine testGame;
	testGame.gameStarted = true;
	testGame.myBoard.piecesOnBoard.push_back(new Queen(0,0,white));
	testGame.myBoard.piecesOnBoard.push_back(new Queen(1,6,white));
	testGame.myBoard.piecesOnBoard.push_back(new Queen(5,5,white));
	testGame.myBoard.piecesOnBoard.push_back(new Queen(6,1,white));

	testGame.myBoard.piecesOnBoard.push_back(new Pawn(0,6,white));
	testGame.myBoard.piecesOnBoard.push_back(new Pawn(0,7,white));
	testGame.myBoard.piecesOnBoard.push_back(new Pawn(1,5,white));
	testGame.myBoard.piecesOnBoard.push_back(new Pawn(1,7,white));
	testGame.myBoard.piecesOnBoard.push_back(new Pawn(2,6,white));
	testGame.myBoard.piecesOnBoard.push_back(new Pawn(6,3,white));
	testGame.myBoard.piecesOnBoard.push_back(new Pawn(7,3,white));
	testGame.myBoard.piecesOnBoard.push_back(new Pawn(3,1,white));
	testGame.myBoard.piecesOnBoard.push_back(new Pawn(0,5,black));
	testGame.myBoard.piecesOnBoard.push_back(new Pawn(2,5,black));
	testGame.myBoard.piecesOnBoard.push_back(new Pawn(5,2,black));
	testGame.myBoard.piecesOnBoard.push_back(new Pawn(7,5,black));
	testGame.myBoard.piecesOnBoard.push_back(new Pawn(7,7,black));

	testGame.turn = white;
	ChessPiece * p1 = testGame.myBoard.piecesOnBoard[1-1];
	ChessPiece * p2 = testGame.myBoard.piecesOnBoard[2-1];
	ChessPiece * p3 = testGame.myBoard.piecesOnBoard[3-1];
	ChessPiece * p4 = testGame.myBoard.piecesOnBoard[4-1];

	p1->setBoard(&testGame.myBoard);
	p2->setBoard(&testGame.myBoard);
	p3->setBoard(&testGame.myBoard);
	p4->setBoard(&testGame.myBoard);

	std::vector<Cell> moves1;
	std::vector<Cell> moves2;
	std::vector<Cell> moves3;
	std::vector<Cell> moves4;

	p1->GetAllPossible(moves1);
	p2->GetAllPossible(moves2);
	p3->GetAllPossible(moves3);
	p4->GetAllPossible(moves4);

	std::vector<Cell>answer1;
	std::vector<Cell>answer2;
	std::vector<Cell>answer3;
	std::vector<Cell>answer4;


	answer1.push_back(Cell(1,0));
	answer1.push_back(Cell(2,0));
	answer1.push_back(Cell(3,0));
	answer1.push_back(Cell(4,0));
	answer1.push_back(Cell(5,0));
	answer1.push_back(Cell(6,0));
	answer1.push_back(Cell(7,0));
	answer1.push_back(Cell(0,1));
	answer1.push_back(Cell(0,2));
	answer1.push_back(Cell(0,3));
	answer1.push_back(Cell(0,4));
	answer1.push_back(Cell(0,5));
	answer1.push_back(Cell(1,1));
	answer1.push_back(Cell(2,2));
	answer1.push_back(Cell(3,3));
	answer1.push_back(Cell(4,4));

	answer2.push_back(Cell(0,5));
	answer2.push_back(Cell(2,5));
	answer2.push_back(Cell(2,7));

	answer3.push_back(Cell(5,2));
	answer3.push_back(Cell(5,3));
	answer3.push_back(Cell(5,4));
	answer3.push_back(Cell(5,6));
	answer3.push_back(Cell(5,7));
	answer3.push_back(Cell(2,5));
	answer3.push_back(Cell(3,5));
	answer3.push_back(Cell(4,5));
	answer3.push_back(Cell(6,5));
	answer3.push_back(Cell(7,5));
	answer3.push_back(Cell(1,1));
	answer3.push_back(Cell(2,2));
	answer3.push_back(Cell(3,3));
	answer3.push_back(Cell(4,4));
	answer3.push_back(Cell(6,6));
	answer3.push_back(Cell(6,4));
	answer3.push_back(Cell(4,6));
	answer3.push_back(Cell(3,7));
	answer3.push_back(Cell(7,7));

	/*
	0 1 2 3 4 5 6 7
	  0 q . . . . P p p TEST 1 (16)
	  1 . . . . . p q p TEST 2 (3)
	  2 . . . . . P p .
	  3 . p . . . . . .
	  4 . . . . . . . .
	  5 . . P . . q . . TEST 3 (18)
	  6 . q . p . . . . TEST 4 (9)
	  7 . . . p . P . P
	  */

	answer4.push_back(Cell(6,0));
	answer4.push_back(Cell(6,2));
	answer4.push_back(Cell(4,1));
	answer4.push_back(Cell(5,1));
	answer4.push_back(Cell(7,1));
	answer4.push_back(Cell(5,0));
	answer4.push_back(Cell(5,2));
	answer4.push_back(Cell(7,2));
	answer4.push_back(Cell(7,0));



	TEST(Pawn::CheckCellVectors(moves1,answer1));
	TEST(Pawn::CheckCellVectors(moves2,answer2));
	TEST(Pawn::CheckCellVectors(moves3,answer3));//
	TEST(Pawn::CheckCellVectors(moves4,answer4));//



	return success;
}

bool Queen::TestCheck(std::ostream &os) {

	bool success = true;
	GameEngine testGame;
	testGame.gameStarted = true;
	testGame.turn = white;

	testGame.myBoard.piecesOnBoard.push_back(new Queen(5,2,white));
	testGame.myBoard.piecesOnBoard.push_back(new Queen(5,3,white));
	testGame.myBoard.piecesOnBoard.push_back(new King(6,3,white));
	testGame.myBoard.piecesOnBoard.push_back(new Queen(3,0,black));
	testGame.myBoard.piecesOnBoard.push_back(new Queen(2,3,black));
	testGame.myBoard.piecesOnBoard.push_back(new Queen(4,4,black));

	ChessPiece * p1 = testGame.myBoard.piecesOnBoard[0];
	ChessPiece * p2 = testGame.myBoard.piecesOnBoard[1];


	std::vector<ChessPiece *>::iterator it;
	for ( it = testGame.myBoard.piecesOnBoard.begin() ;
	        it < testGame.myBoard.piecesOnBoard.end() ; it++) {
		ChessPiece * p = *it;
		p->setBoard(&testGame.myBoard);
	}

	std::vector<Cell> moves1;
	std::vector<Cell> moves2;

	testGame.FindMoves(moves1,p1);
	testGame.FindMoves(moves2,p2);

	std::vector<Cell> answer1;
	std::vector<Cell> answer2;


	answer1.push_back(Cell(4,1));
	answer1.push_back(Cell(3,0));

	answer2.push_back(Cell(4,3));
	answer2.push_back(Cell(3,3));
	answer2.push_back(Cell(2,3));

	TEST(Pawn::CheckCellVectors(moves1,answer1));
	TEST(Pawn::CheckCellVectors(moves2,answer2));

	return success;
}

int Queen::getValue()
{
    return 9;
}


/*
  TEST MOVES------------------------

  Capital = black
  lower = white
  p = pawn
  Q = queen

    0 1 2 3 4 5 6 7
  0 q . . . . P p p TEST 1 (18)
  1 . . . . . p q p TEST 2 (3)
  2 . . . . . P p .
  3 . p . . . . . . TEST 3 (21)
  4 . . . . . . . .
  5 . . P . . q . . TEST 4 (18)
  6 . q . p . . . . TEST 5 (9)
  7 . . . P . P . P

  TEST CHECK------------------------

  Capital = black
  lower = white
  p = pawn
  q = queen
  k = king

    0 1 2 3 4 5 6 7
  0 . . . . . . . .
  1 . . . . . . . .
  2 . . . Q . . . .
  3 Q . . . . . . .
  4 . . . . Q . . .
  5 . . q q . . . . TEST 1 | TEST 2
  6 . . . k . . . .
  7 . . . . . . . .

    0 1 2 3 4 5 6 7
  0 . . . . . . . .
  1 . . . . . . . .
  2 . . . . . . . .
  3 . . . . . . . .
  4 . . . . . . . .
  5 . . . . . . . .
  6 . . . . . . . .
  7 . . . . . . . .


  */
